package com.zzzy.doc.controller.mydoc;

import com.zhuozhengsoft.pageoffice.DocumentOpenType;
import com.zhuozhengsoft.pageoffice.FileMakerCtrl;
import com.zhuozhengsoft.pageoffice.FileSaver;
import com.zhuozhengsoft.pageoffice.word.DataRegionWriter;
import com.zhuozhengsoft.pageoffice.word.DataTagWriter;
import com.zhuozhengsoft.pageoffice.word.WordDocumentWriter;
import com.zzzy.common.util.FileUtil;
import com.zzzy.common.vo.AjaxResult;
import com.zzzy.common.vo.PageResult;
import com.zzzy.doc.common.util.InitDataPageOfficeUtil;
import com.zzzy.doc.dao.entity.DocAdvice;
import com.zzzy.doc.dao.entity.Document;
import com.zzzy.doc.dto.DataRegionDto;
import com.zzzy.doc.service.DocAdviceService;
import com.zzzy.doc.service.mydoc.MyDocService;
import com.zzzy.doc.vo.document.DocBasicInfoRes;
import com.zzzy.doc.vo.document.DocInfoRes;
import com.zzzy.doc.vo.document.my.DocUpdateReq;
import com.zzzy.doc.vo.document.my.MyDocButtonRes;
import com.zzzy.doc.vo.document.my.MyDocPageReq;
import com.zzzy.doc.vo.document.my.MyDocStatisticsRes;
import com.zzzy.doc.vo.pageoffice.OpenOfficeFileRes;
import com.zzzy.framework.common.util.ReflectionUtil;
import com.zzzy.sys.api.UserApi;
import com.zzzy.sys.dto.UserInfoDto;
import com.zzzy.sys.vo.UserSelectPageReq;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.apache.commons.lang3.StringUtils;
import org.springdoc.api.annotations.ParameterObject;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import javax.validation.constraints.NotNull;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;


/**
 * 公文基本信息
 *
 * @author fc
 * @since 2024-08-09
 */
@Tag(name = "我的公文", description = "doc005")
@Validated
@RestController
@RequestMapping("/doc/my")
public class MyDocController {

    @Resource
    private MyDocService myDocService;
    @Resource
    private DocAdviceService docAdviceService;
    @Resource
    protected UserApi userService;

    @Operation(summary = "分页列表")
    @GetMapping(value = "/page")
    @PreAuthorize("@pvs.hasPermission('doc:my:page')")
    public AjaxResult<PageResult<Document>> page(@Valid @ParameterObject MyDocPageReq queryReq) {
        PageResult<Document> docPage = myDocService.getMyDocPage(queryReq);
        return AjaxResult.success(docPage);
    }

    @GetMapping("/getDocBasicInfo/{id}")
    @Operation(summary = "获取公文基本信息")
    @Parameter(name = "id", description = "公文ID", required = true)
    @PreAuthorize("@pvs.hasPermission('doc:my:page')")
    public AjaxResult<DocBasicInfoRes> getDocBasicInfo(@NotNull(message = "公文ID不能为空") @PathVariable("id") Long id) {
        DocBasicInfoRes doc = myDocService.getDocBasicInfo(id);
        return AjaxResult.success(doc);
    }

    @GetMapping("/getDocImage/{id}")
    @Operation(summary = "获取公文正文第一页缩略图")
    @Parameter(name = "id", description = "公文ID", required = true)
    @PreAuthorize("@pvs.hasPermission('doc:my:page')")
    public void getDocImage(@NotNull(message = "公文ID不能为空") @PathVariable("id") Long id, HttpServletResponse response) {
        Document doc = myDocService.getDocByIdForQuery(id);
        FileUtil.outputFileStream(response, doc.getDocThumbnailBlob(), doc.getSubject());
    }

    @PutMapping("/update")
    @Operation(summary = "修改公文基本信息")
    @PreAuthorize("@pvs.hasPermission('doc:my:update')")
    public AjaxResult update(@Valid @RequestBody DocUpdateReq updateReq) {
        myDocService.updateById(updateReq);
        return AjaxResult.success();
    }

    @PostMapping("/approvalAutoFill/{id}")
    @Operation(summary = "呈批表自动填充")
    @Parameter(name = "id", description = "公文ID", required = true)
    @PreAuthorize("@pvs.hasPermission('doc:my:update')")
    public void approvalAutoFill(@NotNull(message = "公文ID不能为空") @PathVariable("id") Long id
            , HttpServletRequest request, HttpServletResponse response) throws IOException {
        DocBasicInfoRes docBasicInfo = myDocService.getDocBasicInfo(id);

        String openFileUrl = "/doc/my/getApprovalDocFileStream/" + id;
        FileMakerCtrl fmCtrl = new FileMakerCtrl(request);
        //数据区域自动填充
        WordDocumentWriter doc = new WordDocumentWriter();
        for (DataRegionDto dataRegion : docBasicInfo.getApprovalDataRegions()) {
            if (StringUtils.isBlank(dataRegion.getStatus())){
                DataRegionWriter dataRegionWriter = doc.openDataRegion(dataRegion.getName());
                Object fieldValue = ReflectionUtil.getFieldValue(docBasicInfo, dataRegion.getName());
                String value = Objects.isNull(fieldValue) ? "" : String.valueOf(fieldValue);
                dataRegionWriter.setValue(value);
            }
        }
        fmCtrl.setWriter(doc);
        fmCtrl.fillDocumentAs(openFileUrl, DocumentOpenType.Word, docBasicInfo.getSubject());
        response.getOutputStream().print(fmCtrl.getHtml());
    }

    @PostMapping("/nextApprovalAutoFill/{id}")
    @Operation(summary = "进入下一步前（审核、会签、签批）呈批表自动填充，删除多余文本")
    @Parameter(name = "id", description = "公文ID", required = true)
    @PreAuthorize("@pvs.hasPermission('doc:my:update')")
    public void nextApprovalAutoFill(@NotNull(message = "公文ID不能为空") @PathVariable("id") Long id
            , HttpServletRequest request, HttpServletResponse response) throws IOException {
        DocBasicInfoRes docBasicInfo = myDocService.getDocBasicInfo(id);

        String openFileUrl = "/doc/my/getApprovalDocFileStream/" + id;
        FileMakerCtrl fmCtrl = new FileMakerCtrl(request);
        //数据标签自动填充
        WordDocumentWriter doc = new WordDocumentWriter();
        Map<String, DataRegionDto> statusDataRegionMap = InitDataPageOfficeUtil.getInitDataRegionList().stream()
                .filter(dataRegion -> docBasicInfo.getStatus().equals(dataRegion.getStatus())).collect(Collectors.toMap(DataRegionDto::getName, d-> d));
        for (DataRegionDto dataRegion : docBasicInfo.getApprovalDataRegions()) {
            DataRegionDto replaceDataRegion = statusDataRegionMap.get(dataRegion.getName());
            if (Objects.nonNull(replaceDataRegion)){
                DataTagWriter dataTag = doc.openDataTag(replaceDataRegion.getValue());
                dataTag.setValue("        ");
            }
        }
        fmCtrl.setWriter(doc);
        fmCtrl.fillDocumentAs(openFileUrl, DocumentOpenType.Word, docBasicInfo.getSubject());
        response.getOutputStream().print(fmCtrl.getHtml());
    }
    @GetMapping(value = "/getApprovalPageOfficeFile/{id}")
    @Operation(summary = "打开呈批表文件")
    @Parameter(name = "id", description = "公文ID", required = true)
    @PreAuthorize("@pvs.hasPermission('doc:my:page')")
    public AjaxResult<OpenOfficeFileRes> getApprovalPageOfficeFile(@NotNull(message = "公文ID不能为空") @PathVariable("id") Long id) {
        String openFileUrl = "/doc/my/getApprovalDocFileStream/" + id;
        OpenOfficeFileRes openOfficeFileRes = myDocService.getApprovalPageOfficeResByDocId(id, openFileUrl);
        return AjaxResult.success(openOfficeFileRes);
    }

    @GetMapping(value = "/getApprovalDocFileStream/{id}")
    @Operation(summary = "获取呈批表文件流")
    @Parameter(name = "id", description = "公文ID", required = true)
    @PreAuthorize("@pvs.hasPermission('doc:my:page')")
    public void getApprovalDocFileStream(@NotNull(message = "公文ID不能为空") @PathVariable("id") Long id, HttpServletResponse response) {
        DocInfoRes docInfo = myDocService.getDocInfo(id);
        byte[] fileBlob = docInfo.getApprovalFileBlob();
        FileUtil.outputFileStream(response, fileBlob, docInfo.getSubject() + "." + FileUtil.getFileType(fileBlob));
    }

    @PostMapping(value = "/updateApprovalWord/{id}")
    @Operation(summary = "保存呈批表文件")
    @Parameter(name = "id", description = "公文ID", required = true)
    @Parameter(name = "revisionCount", description = "修订痕迹数量", required = true)
    @PreAuthorize("@pvs.hasPermission('doc:my:update')")
    public void updateApprovalWord(@NotNull(message = "公文ID不能为空") @PathVariable("id") Long id, HttpServletRequest request, HttpServletResponse response) {
        FileSaver fs = new FileSaver(request, response);
        myDocService.updateApprovalWord(id, fs.getFileBytes());
        fs.setCustomSaveResult("ok");
        fs.close();
    }

    @GetMapping(value = "/getMainPageOfficeFile/{id}")
    @Operation(summary = "打开正文文件")
    @Parameter(name = "id", description = "公文ID", required = true)
    @PreAuthorize("@pvs.hasPermission('doc:my:page')")
    public AjaxResult<OpenOfficeFileRes> getMainPageOfficeFile(@NotNull(message = "公文ID不能为空") @PathVariable("id") Long id) {
        String openFileUrl = "/doc/my/getMainDocFileStream/" + id;
        OpenOfficeFileRes openOfficeFileRes = myDocService.getMainPageOfficeResByDocId(id, openFileUrl);
        return AjaxResult.success(openOfficeFileRes);
    }

    @GetMapping(value = "/getMainDocFileStream/{id}")
    @Operation(summary = "获取正文文件流")
    @Parameter(name = "id", description = "公文ID", required = true)
    @PreAuthorize("@pvs.hasPermission('doc:my:page')")
    public void getMainDocFileStream(@NotNull(message = "公文ID不能为空") @PathVariable("id") Long id, HttpServletResponse response) {
        DocInfoRes docInfo = myDocService.getDocInfo(id);
        byte[] fileBlob = docInfo.getMainFileBlob();
        FileUtil.outputFileStream(response, fileBlob, docInfo.getSubject() + "." + FileUtil.getFileType(fileBlob));
    }

    @PostMapping(value = "/updateMainWord")
    @Operation(summary = "保存正文文件")
    @Parameter(name = "id", description = "公文ID", required = true)
    @Parameter(name = "revisionCount", description = "修订痕迹数量", required = true)
    @PreAuthorize("@pvs.hasPermission('doc:my:update')")
    public void updateMainWord(@NotNull(message = "公文ID不能为空") @RequestParam("id") Long id, Integer revisionCount,
                               HttpServletRequest request, HttpServletResponse response) {
        FileSaver fs = new FileSaver(request, response);
        revisionCount = revisionCount == null ? 0 : revisionCount;
        myDocService.updateMainWord(id, fs.getFileBytes(), revisionCount);
        String documentText = fs.getDocumentText();
        myDocService.updateMainText(id, documentText);
        fs.setCustomSaveResult("ok");
        fs.close();
    }

    @PostMapping(value = "/updateMainImage/{id}")
    @Operation(summary = "保存正文首页缩略图")
    @Parameter(name = "id", description = "公文ID", required = true)
    @PreAuthorize("@pvs.hasPermission('doc:my:update')")
    public void updateMainImage(@NotNull(message = "公文ID不能为空") @PathVariable("id") Long id, HttpServletRequest request, HttpServletResponse response) {
        FileSaver fs = new FileSaver(request, response);
        myDocService.updateMainImage(id, fs.getFileBytes());
        fs.setCustomSaveResult("ok");
        fs.close();
    }

    @GetMapping(value = "/getFinalPageOfficeFile/{id}")
    @Operation(summary = "打开最终文件（合并后的pdf）")
    @Parameter(name = "id", description = "公文ID", required = true)
    @PreAuthorize("@pvs.hasPermission('doc:my:page')")
    public AjaxResult<OpenOfficeFileRes> getFinalPageOfficeFile(@NotNull(message = "公文ID不能为空") @PathVariable("id") Long id) {
        String openFileUrl = "/doc/my/getFinalDocFileStream/" + id;
        OpenOfficeFileRes openOfficeFileRes = myDocService.getFinalPageOfficeResByDocId(id, openFileUrl);
        return AjaxResult.success(openOfficeFileRes);
    }

    @GetMapping(value = "/getFinalDocFileStream/{id}")
    @Operation(summary = "获取最终文件流（合并后的pdf）")
    @Parameter(name = "id", description = "公文ID", required = true)
    @PreAuthorize("@pvs.hasPermission('doc:my:page')")
    public void getFinalDocFileStream(@NotNull(message = "公文ID不能为空") @PathVariable("id") Long id, HttpServletResponse response) {
        DocInfoRes docInfo = myDocService.getDocInfo(id);
        byte[] fileBlob = docInfo.getPdfFileBlob();
        FileUtil.outputFileStream(response, fileBlob, docInfo.getSubject() + "." + FileUtil.PDF);
    }

    @GetMapping("/getButton/{id}")
    @Operation(summary = "获取公文可操作按钮")
    @Parameter(name = "id", description = "公文ID", required = true)
    @PreAuthorize("@pvs.hasPermission('doc:my:page')")
    public AjaxResult<MyDocButtonRes> getButton(@NotNull(message = "公文ID不能为空") @PathVariable("id") Long id) {
        MyDocButtonRes buttonRes = myDocService.getButton(id);
        return AjaxResult.success(buttonRes);
    }

    @Operation(summary = "选择办理人分页列表")
    @GetMapping(value = "/userSelectPage")
    @PreAuthorize("@pvs.hasPermission('doc:my:page')")
    public AjaxResult<PageResult<UserInfoDto>> userSelectPage(@Valid @ParameterObject UserSelectPageReq queryReq) {
        PageResult<UserInfoDto> userPage = userService.userSelectPage(queryReq);
        return AjaxResult.success(userPage);
    }

    @PutMapping("/cancel/{id}")
    @Operation(summary = "作废公文")
    @Parameter(name = "id", description = "公文ID", required = true)
    @PreAuthorize("@pvs.hasPermission('doc:my:update')")
    public AjaxResult cancel(@NotNull(message = "公文ID不能为空") @PathVariable("id") Long id) {
        myDocService.cancel(id);
        return AjaxResult.success();
    }

    @Operation(summary = "意见汇总列表列表")
    @GetMapping(value = "/getAdviceList/{id}")
    @Parameter(name = "id", description = "公文ID", required = true)
    @PreAuthorize("@pvs.hasPermission('doc:my:page')")
    public AjaxResult<List<DocAdvice>> getAdviceList(@NotNull(message = "公文ID不能为空") @PathVariable("id") Long id) {
        List<DocAdvice> adviceList = docAdviceService.getAdviceListDocId(id);
        return AjaxResult.success(adviceList);
    }

    @Operation(summary = "统计信息")
    @GetMapping(value = "/getStatistics")
    @PreAuthorize("@pvs.hasPermission('doc:my:page')")
    public AjaxResult<MyDocStatisticsRes> getStatistics() {
        MyDocStatisticsRes statistics = myDocService.getStatistics();
        return AjaxResult.success(statistics);
    }
}
